# def 定义函数，函数返回关键字return ，函数没有返回值，默认是None

def say(name, age):
    print('%s age is %d' % (name, age))


say('小明', 18)
say(age=20, name='小红')


# py可以不指定函数形参的数据类型，如果需要可以加上
def say_hi(num: int):
    pass


# 全局变量和局部变量
a = 100
b = 10


def test1():
    a = 10
    print('a=%d' % a)
    global b
    b = 100

    # 查看所有的局部变量和全局变量
    print(locals(), globals())


# 参数缺省
def test2(name, age=18):
    print('%s age is %d' % (name, age))


test2('xiaoming')

test1()

print('a=%d' % a)
print('b=%d' % b)


# *args 表示可变位置参数,**kwargs 可变关键字参数
# args 和kwargs 只是名字，可以改变，但一般默认约定这个命名
def test3(a, b, *args, **kwargs):
    # args元组 kwargs 字典
    print(args, kwargs)


test3(1, 2, 3, 4)

test3(5, 6, 99, age=18)

# python不允许函数名同名，也不允许函数名和变量名同名，函数名相当于一个变量名，可以动态被赋值，因此定义变量名和函数名不要使用内置函数名
# 相同函数名最后一个函数会覆盖前一个函数
# def test4():
#     pass
#
# def test4(a):
#     pass

# test4()

# def test4():
#     pass
#
# test4 = 5
#
# print(type(test4))

# 内置函数名被重复使用，input就变成了int数据而不是函数，当函数使用就会报错
# input = 88

# 可变类型和不可变类型
b = 100
print('调用前b=%x' % id(b))


def test5(x):
    print('赋值前x=%x' % id(x))
    x = 10
    print('赋值后x=%x' % id(x))


test5(b)
print('b=%d' % b)  # 值没有改变
print('调用后b=%x' % id(b))

c = [1, 2, 3]
print('调用前c=%x' % id(c))


def test6(x):
    print('赋值前x=%x' % id(x))
    x[0] = 10
    print('赋值后x=%x' % id(x))


test6(c)
print('c=%s' % c)  # 列表元素改变
print('调用后c=%x' % id(c))

# 匿名函数：函数调用次数很少，基本调用一次

mul = lambda a, b: a + b
print(mul(1, 2))


# 高阶函数
def test7(a, b, fn):
    return fn(a, b)


print(test7(2, 3, lambda x, y: x * y))

d = [{'age': 100}, {'age': 10}, {'age': 19}, {'age': 15}]

d.sort(key=lambda dict: dict['age'])

print(d)

# filter/map/reduce

e = [15, 16, 4, 6, 88]
result1 = filter(lambda x: x > 18, e)  # 得到的结果是一个迭代器，需要包装下
print(list(result1))

result2 = map(lambda x: x + 2, e)
print(list(result2))

from functools import reduce

result3 = reduce(lambda x, y: x + y, e)
print(result3)

# 最后一个参数是初始值，即x的初始值为0
result4 = reduce(lambda x, y: x + y['age'], d, 0)
print(result4)

# all()所有元素的布尔值都是True，才会是True,否则是False
print(all(['f', 100]))
print(all([5, '']))

# any()只要有一个元素是True，就会为True，否则是False
print(any(['', 0]))
print(any([5, '']))


# dir 列出所以对象的属性和方法
print(dir(''))

# issubclass() isinstance()

# repr()对象变成字符串
result5 = repr(d)
print(type(result5))


def test_outer():
    print('test_outer')
    def test_inner():
        print('test_inner')

# 调用test_inner
# test_outer()testinner()







